#include "stdafx.h"

#include <cassert>
#include <vector>
#include <string>

#include "asset.h"
#include "model.h"
#include "assimp.hpp"
#include "aiPostProcess.h"
#include "aiScene.h"
#include <memory>
#include "geom.h"

using namespace std;
namespace asset
{
	Model mesh_to_model(const aiScene* scene, const aiMesh* mesh)
	{
		Model model;
		model.geometry = shared_ptr<Geometry>(new Geometry(mesh->mNumVertices, sizeof(StaticVertex), mesh->mNumFaces * 3));

		auto vert_pointer = (StaticVertex*)model.geometry->vertices_pointer();
		for(uint i = 0; i < mesh->mNumVertices; i++)
		{
			vert_pointer[i].position = float3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
			if(mesh->HasNormals())
			{
				vert_pointer[i].normal = float3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
			}
			if(mesh->HasTangentsAndBitangents())
			{
				vert_pointer[i].tangent = float3(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z);
				vert_pointer[i].bitangent = float3(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z);
			}
			if(mesh->HasTextureCoords(0))
			{
				vert_pointer[i].uv = float2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
			}
		}
		auto index_pointer = model.geometry->indexes_pointer();
		for(uint i = 0; i < mesh->mNumFaces; i++)
		{			
			if(mesh->mFaces[i].mNumIndices == 3)
			{
				index_pointer[i * 3 + 0] = mesh->mFaces[i].mIndices[0];
				index_pointer[i * 3 + 1] = mesh->mFaces[i].mIndices[1];
				index_pointer[i * 3 + 2] = mesh->mFaces[i].mIndices[2];	
			}		
		}
		if(scene->mMaterials[mesh->mMaterialIndex]->GetTextureCount(aiTextureType_DIFFUSE) > 0)
		{
			aiString texture_path;
			scene->mMaterials[mesh->mMaterialIndex]->GetTexture(aiTextureType_DIFFUSE, 0, &texture_path );
			std::string tp(texture_path.data);
			model.material.albedo = std::wstring(tp.begin(), tp.end()).c_str();
		}
		if(scene->mMaterials[mesh->mMaterialIndex]->GetTextureCount(aiTextureType_HEIGHT) > 0)
		{
			aiString texture_path;
			scene->mMaterials[mesh->mMaterialIndex]->GetTexture(aiTextureType_HEIGHT, 0, &texture_path );
			std::string tp(texture_path.data);
			model.material.normal = std::wstring(tp.begin(), tp.end()).c_str();
		}
		return model;
	}
	ModelGroup asset_to_modelgroup(const char* path)
	{		
		ModelGroup model_group;
		Assimp::Importer importer;
		auto scene = importer.ReadFile( path, 
			aiProcess_CalcTangentSpace       | 
			aiProcess_Triangulate            |
			aiProcess_JoinIdenticalVertices  |
			aiProcess_PreTransformVertices   |
			aiProcess_FlipUVs			     |
			aiProcess_SortByPType);
		for(uint i = 0; i < scene->mNumMeshes; i++)
		{
			model_group.push_back(mesh_to_model(scene, scene->mMeshes[i]));
		}
		return model_group;
	}
}